We decided to focus on the question "what is the best character/vehicle combination in Mario Kart Wii?" This question is relevant because the community around the game is still active through community created servers, mods, and speedruns. The community seems to be unanimous in saying that Daisy on the Mach bike and Funky Kong on the Flame Runner are the best combinations. We wondered why that was and if there's substance behind those claims.
Our intended audience is anyone that plays Mario Kart Wii. Like we said, the community is still very active and the game has a considerable following both in Wegatz in general and Third East Wengatz specifically.
We've chosen to analize vehicle and character statistics and characteristics as well as speed running data. We chose the character/vehicle data source because it would provide valuable insight into what advantages a particular character/vehicle might have. The data source is popular in the community and is frequently cited. Speedrunning data was used to show what combinations speedrunners were using. We figured that, since Mario Kart is a racing game, going fast and staying in control enough to maneuver around sudden obsticals and take opportunities (such as a dropped mushroom boost), would be the forte of the speedrunning community. Knowing what combinations of characters and vehicles the speedrunning community is using would be helpful both to show what is popular and to act as a loose guide of what we could expect the outcome to be.
Character/vehicle statistics data source: Kaggle
Speedrunning data source: Speedrun
Speedrunning data api: Github
Additional data source for drift information (entered manually): Gamefaqs
Mario Kart Wii characteristics explanation: Wordpress
We mostly used plotly and pandas to work with and show data. We also used an api to acess speedrunning data. More specifically, we utilized filtering to cut out characters and vehicles that did not fit our minimum criteria for viability. This would allow us to create a pool of vehicles that are at least as close to Daisy/Mach Bike and Funky Kong/Flame Runner combinations. If this pool was every vehicle/character in the game, then we could reasonably say that either vehicle/character combinations don't matter as much or the aforementioned combinations are actually really poor combinations.
We mostly stuck with simple bar charts for our visualizations, however, we also utilized some histogram graphics and a scatterplot. We chose to primarily stick with bar charts because they were able to show what we wanted the audience to see when we wanted them to see it. We went through a few different criteria filters to reach our conclusion, however, not all criteria is created equal. For example, we decided speed would be our primary criteria since that made the most amount of sense in a race. We thought that the audience might miss what we were doing at each stage of the filtering process if we included more than one of our filtering criteria at once before we reached our conclusion. We used a histogram to display popularity of character/vehicle combinations among the speedrunning community. We used a scatterplot to show vehicles graphed as a function of two of our most important criteria.
We labeled as much as we could to keep misunderstandings to a minimum. We were worried that some of our early bar graphs from before our filtering criteria would make it hard for the audience to see the actual value associated with each bar. To get around this, we put the bar's value inside the bar. We were also worried that the audience would misunderstand what characters could drive which vehicles. Therefore, we color coded our bar graphs in a consistent way to make it clear what weight class each character and vehicle was in.
We hope that our audience comes away with a better understanding of the game, what criteria is important when selecting a character/vehicle and what some general trends among the vehicles are. For example, very fast vehicles don't typically have great acceleration.
import pandas as pd
import plotly.express as px
bikes = pd.read_csv('./data/bikes.csv')
characters = pd.read_csv('./data/characters.csv')
karts = pd.read_csv('./data/karts.csv')
bikes.rename(columns={'Bike':'Name'}, inplace=True)
bikes['Type'] = 'Bike'
karts.rename(columns={'Kart':'Name'}, inplace=True)
karts['Type'] = 'Kart'
characters
| Character | Class | Speed | Weight | Acceleration | Handling | Drift | Off-Road | Mini-Turbo | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | Baby Mario | Light | 0 | 8 | 0 | 6 | 0 | 0 | 0 |
| 1 | Baby Luigi | Light | 5 | 8 | 0 | 0 | 0 | 0 | 0 |
| 2 | Baby Peach | Light | 3 | 6 | 3 | 3 | 0 | 0 | 0 |
| 3 | Baby Daisy | Light | 5 | 6 | 0 | 0 | 0 | 0 | 3 |
| 4 | Toad | Light | 0 | 0 | 6 | 0 | 6 | 0 | 0 |
| 5 | Toadette | Light | 3 | 0 | 0 | 0 | 0 | 6 | 0 |
| 6 | Koopa Troopa | Light | 0 | 0 | 0 | 3 | 0 | 0 | 6 |
| 7 | Dry Bones | Light | 0 | 0 | 3 | 0 | 3 | 0 | 3 |
| 8 | Mii S | Light | 3 | 3 | 0 | 0 | 3 | 0 | 3 |
| 9 | Mario | Medium | 0 | 6 | 2 | 2 | 3 | 0 | 0 |
| 10 | Luigi | Medium | 2 | 6 | 0 | 0 | 0 | 0 | 0 |
| 11 | Peach | Medium | 2 | 0 | 5 | 0 | 6 | 0 | 0 |
| 12 | Daisy | Medium | 4 | 0 | 0 | 2 | 0 | 0 | 3 |
| 13 | Yoshi | Medium | 0 | 3 | 0 | 0 | 3 | 5 | 0 |
| 14 | Birdo | Medium | 0 | 3 | 0 | 0 | 0 | 3 | 4 |
| 15 | Diddy Kong | Medium | 0 | 0 | 3 | 0 | 3 | 0 | 5 |
| 16 | Bowser Jr. | Medium | 0 | 0 | 0 | 0 | 0 | 3 | 3 |
| 17 | Mii M | Medium | 3 | 3 | 0 | 0 | 0 | 3 | 3 |
| 18 | Wario | Heavy | 0 | 3 | 0 | 0 | 0 | 3 | 6 |
| 19 | Waluigi | Heavy | 0 | 0 | 6 | 0 | 5 | 3 | 0 |
| 20 | Donkey Kong | Heavy | 0 | 3 | 2 | 2 | 0 | 0 | 3 |
| 21 | Bowser | Heavy | 2 | 5 | 0 | 0 | 3 | 0 | 0 |
| 22 | King Boo | Heavy | 0 | 0 | 0 | 5 | 0 | 3 | 0 |
| 23 | Rosalina | Heavy | 3 | 0 | 0 | 3 | 0 | 0 | 3 |
| 24 | Funky Kong | Heavy | 4 | 0 | 0 | 0 | 0 | 3 | 0 |
| 25 | Dry Bowser | Heavy | 0 | 0 | 0 | 0 | 0 | 6 | 6 |
| 26 | Mii L | Heavy | 3 | 0 | 3 | 3 | 3 | 0 | 0 |
vehicles = pd.concat([karts, bikes])
vehicles
| Name | Class | Speed | Weight | Acceleration | Handling | Drift | Off-Road | Mini-Turbo | Type | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Standard Kart S | Light | 41 | 29 | 48 | 48 | 51 | 30 | 45 | Kart |
| 1 | Booster Seat | Light | 27 | 27 | 56 | 64 | 37 | 54 | 59 | Kart |
| 2 | Mni Beast | Light | 55 | 32 | 29 | 32 | 64 | 27 | 64 | Kart |
| 3 | Cheep Charger | Light | 34 | 24 | 64 | 56 | 59 | 45 | 54 | Kart |
| 4 | Tiny Titan | Light | 46 | 35 | 43 | 43 | 29 | 64 | 40 | Kart |
| 5 | Blue Falcon | Light | 60 | 29 | 35 | 29 | 43 | 24 | 29 | Kart |
| 6 | Standard Kart M | Medium | 46 | 45 | 40 | 43 | 45 | 35 | 40 | Kart |
| 7 | Classic Dragster | Medium | 37 | 43 | 59 | 54 | 54 | 40 | 51 | Kart |
| 8 | Wild Wing | Medium | 57 | 51 | 21 | 29 | 59 | 24 | 59 | Kart |
| 9 | Super Blooper | Medium | 50 | 40 | 35 | 37 | 21 | 54 | 35 | Kart |
| 10 | Daytripper | Medium | 34 | 45 | 51 | 59 | 32 | 48 | 54 | Kart |
| 11 | Sprinter | Medium | 64 | 48 | 27 | 24 | 37 | 21 | 24 | Kart |
| 12 | Standard Kart L | Heavy | 48 | 59 | 37 | 40 | 40 | 35 | 35 | Kart |
| 13 | Offroader | Heavy | 39 | 64 | 48 | 54 | 18 | 43 | 45 | Kart |
| 14 | Flame Flyer | Heavy | 62 | 59 | 16 | 21 | 48 | 18 | 48 | Kart |
| 15 | Pirhanha Prowler | Heavy | 55 | 67 | 29 | 35 | 35 | 29 | 27 | Kart |
| 16 | Jetsetter | Heavy | 69 | 56 | 21 | 17 | 27 | 16 | 16 | Kart |
| 17 | Honeycoupe | Heavy | 53 | 62 | 17 | 19 | 56 | 24 | 56 | Kart |
| 0 | Standard Bike S | Light | 39 | 21 | 51 | 51 | 54 | 43 | 48 | Bike |
| 1 | Bullet Bike | Light | 53 | 24 | 32 | 35 | 67 | 29 | 67 | Bike |
| 2 | Bit Bike | Light | 25 | 18 | 59 | 67 | 40 | 56 | 62 | Bike |
| 3 | Quacker | Light | 32 | 17 | 67 | 60 | 63 | 48 | 57 | Bike |
| 4 | Magikruiser | Light | 43 | 24 | 45 | 45 | 32 | 67 | 43 | Bike |
| 5 | Jet Bubble | Light | 48 | 27 | 40 | 40 | 45 | 35 | 37 | Bike |
| 6 | Standard Bike M | Medium | 46 | 45 | 40 | 43 | 45 | 35 | 40 | Bike |
| 7 | Mach Bike | Medium | 55 | 37 | 24 | 32 | 62 | 27 | 62 | Bike |
| 8 | Sugarscoot | Medium | 32 | 32 | 54 | 62 | 35 | 51 | 56 | Bike |
| 9 | Zip Zip | Medium | 41 | 35 | 45 | 51 | 29 | 62 | 45 | Bike |
| 10 | Sneakster | Medium | 62 | 40 | 29 | 27 | 40 | 24 | 27 | Bike |
| 11 | Dolphin Dasher | Medium | 48 | 43 | 37 | 40 | 24 | 56 | 37 | Bike |
| 12 | Standard Bike L | Heavy | 46 | 54 | 40 | 43 | 43 | 37 | 37 | Bike |
| 13 | Flame Runner | Heavy | 60 | 54 | 18 | 24 | 51 | 21 | 51 | Bike |
| 14 | Wario Bike | Heavy | 37 | 59 | 51 | 56 | 21 | 45 | 48 | Bike |
| 15 | Shooting Star | Heavy | 50 | 48 | 29 | 32 | 59 | 27 | 59 | Bike |
| 16 | Spear | Heavy | 67 | 56 | 24 | 18 | 29 | 18 | 18 | Bike |
| 17 | Phantom | Heavy | 43 | 51 | 43 | 48 | 17 | 56 | 40 | Bike |
bar = px.bar(vehicles, x='Name', y='Speed', color='Class', text_auto='.2s', title='Speeds of Vehicles Grouped by Weight Class')
bar.update_yaxes(showticklabels=True, tickmode = 'array', tickvals=[0, 20, 40, 60, 80])
bar.show()
filtered_vehicles = vehicles.loc[vehicles['Speed'] >= 50]
bar = px.bar(filtered_vehicles, x='Name', y='Speed', color='Class', text_auto='.2s', title='Speeds of Viable Vehicles Grouped by Weight Class')
bar.update_yaxes(showticklabels=True, tickmode = 'array', tickvals=[0, 20, 40, 60, 80])
bar.show()
bar = px.bar(characters, x='Character', y='Speed', color='Class', text_auto='.2s', title='Speed Modifications of Characters Grouped by Weight Class')
bar.show()
bar = px.bar(filtered_vehicles, x='Name', y='Drift', color='Class', text_auto='.2s', title='Drift Stats of Vehicles Grouped by Weight Class')
bar.show()
bar = px.bar(characters, x='Character', y='Drift', color='Class', text_auto='.2s', title='Drift Modifications of Characters Grouped by Weight Class')
bar.show()
filtered_vehicles = filtered_vehicles.loc[filtered_vehicles['Drift'] >= 45]
bar = px.bar(filtered_vehicles, x='Name', y='Speed', color='Class', text_auto='.2s', title='Speed Stats of Vehicles Grouped by Weight Class')
viable = filtered_vehicles.sort_values(by=['Class', 'Speed', 'Drift', 'Mini-Turbo'], ascending=False).reset_index().drop(columns=['index'])
viable['Drift_Type'] = 'Outside'
for i in [1, 3, 5]:
viable.iat[i, viable.columns.get_loc('Drift_Type')] = 'Inside'
viable
| Name | Class | Speed | Weight | Acceleration | Handling | Drift | Off-Road | Mini-Turbo | Type | Drift_Type | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Wild Wing | Medium | 57 | 51 | 21 | 29 | 59 | 24 | 59 | Kart | Outside |
| 1 | Mach Bike | Medium | 55 | 37 | 24 | 32 | 62 | 27 | 62 | Bike | Inside |
| 2 | Mni Beast | Light | 55 | 32 | 29 | 32 | 64 | 27 | 64 | Kart | Outside |
| 3 | Bullet Bike | Light | 53 | 24 | 32 | 35 | 67 | 29 | 67 | Bike | Inside |
| 4 | Flame Flyer | Heavy | 62 | 59 | 16 | 21 | 48 | 18 | 48 | Kart | Outside |
| 5 | Flame Runner | Heavy | 60 | 54 | 18 | 24 | 51 | 21 | 51 | Bike | Inside |
| 6 | Honeycoupe | Heavy | 53 | 62 | 17 | 19 | 56 | 24 | 56 | Kart | Outside |
| 7 | Shooting Star | Heavy | 50 | 48 | 29 | 32 | 59 | 27 | 59 | Bike | Outside |
fig = px.scatter(viable, y='Speed', x='Drift', color='Drift_Type', text='Name', title='Speed and Drift of Viable Vehicles Grouped by Drift Type')
fig.update_traces(textposition='bottom center')
fig.show()